﻿using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using RpcHelper;
using RpcModular.Domain;
using RpcModularModel.Shield.Msg;

namespace RpcModular.Service
{

    internal class ResourceShieldService : IResourceShieldService
    {
        private readonly ConcurrentDictionary<string, ResourceShield> _ShieldCache = new ConcurrentDictionary<string, ResourceShield>();
        private Timer _CheckTime;

        private void _Refresh(RefreshShieId obj)
        {
            if (this._ShieldCache.TryGetValue(obj.Path, out ResourceShield shield))
            {
                shield.ResetLock();
            }
        }

        private bool _Get(string path, out ResourceShield shield)
        {
            if (!this._ShieldCache.TryGetValue(path, out shield))
            {
                shield = this._ShieldCache.GetOrAdd(path, new ResourceShield(path));
            }
            if (!shield.Init())
            {
                this._ShieldCache.TryRemove(path, out shield);
                shield.Dispose();
                return false;
            }
            return shield.IsInit;
        }
        public bool CheckIsShieId(string path)
        {
            if (!this._Get(path, out ResourceShield shield))
            {
                throw new ErrorException(shield.Error);
            }
            return shield.IsShieId;
        }
        public void Dispose()
        {
            this._CheckTime?.Dispose();
            this._CheckTime = null;
            RpcClient.RpcClient.Route.RemoveRoute("RefreshShieId");
            this._ShieldCache.Clear();
        }

        public void Init()
        {
            if (this._CheckTime == null)
            {
                this._CheckTime = new Timer(this._Check, null, 1000, 1000);
            }
            if (!RpcClient.RpcClient.Route.CheckIsExists("RefreshShieId"))
            {
                RpcClient.RpcClient.Route.AddRoute<RefreshShieId>(this._Refresh);
            }
        }

        private void _Check(object state)
        {
            if (this._ShieldCache.IsEmpty) { return; }
            string[] keys = this._ShieldCache.Keys.ToArray();
            long now = DateTime.Now.ToLong();
            keys.ForEach(a =>
            {
                this._ShieldCache[a].CheckIsOverTime(now);
            });
        }
    }
}
